home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swagg_m.zip / MEMORY.SWG / 0005_FASTMEM.PAS.pas < prev    next >
Pascal/Delphi Source File  |  1993-05-28  |  5KB  |  173 lines

  1. Unit MEM16;
  2. {
  3.  Author:        Paul VanderSpek
  4.  Date:          03-20-1993
  5.  
  6.     This source code is being released as Free-Ware.  You may use
  7.   this code in your Programs and modify it to fit your needs. The
  8.   only  restrictions are that you  may not distribute the  source
  9.   code in modified Form or Charge For the source code itself.
  10.  
  11.  
  12. }
  13.  
  14. Interface
  15.  
  16. Procedure Move16(Var Source,Dest;Count:Word);
  17. Procedure FillChar16(Var X; Count: Word; Value:Byte);
  18.  
  19. Implementation
  20.  
  21. Procedure Move16(Var Source,Dest;Count:Word); Assembler;
  22. Asm
  23.   PUSH DS
  24.   LDS SI,SOURCE
  25.   LES DI,DEST
  26.   MOV AX,COUNT
  27.   MOV CX,AX
  28.   SHR CX,1
  29.   REP MOVSW
  30.   TEST AX,1
  31.   JZ @end
  32.   MOVSB
  33. @end:POP DS
  34. end;
  35.  
  36. Procedure FillChar16(Var X; Count: Word; Value:Byte); Assembler;
  37. Asm
  38.   LES DI,X
  39.   MOV CX,COUNT
  40.   SHR CX,1
  41.   MOV AL,ValUE
  42.   MOV AH,AL
  43.   REP StoSW
  44.   TEST COUNT,1
  45.   JZ @end
  46.   StoSB
  47. @end:
  48. end;
  49.  
  50. end.
  51.  
  52. {
  53. These routines are twice as fast as the normal Move and FillChar routines
  54. sInce they use MOVSW and StoSW instead of MOVSB and StoSB. They work in
  55. exactly the same way, so you can just replace Move and FillChar With them.
  56. }
  57.  
  58. {
  59. >     This source code is being released as Free-Ware.  You may use
  60. >   this code in your Programs and modify it to fit your needs. The
  61. >   only  restrictions are that you  may not distribute the  source
  62. >   code in modified form or Charge For the source code itself.
  63.  
  64. I'm sorry to say that I'm not impressed, since hundreds of people already have
  65. invented this wheel.  Besides, your move routine has at least one serious flaw:
  66. it assumes that source and destinaton do not overlap.  Which is not always the
  67. case; if you have a Variable of the Type String as the source, and you want to
  68. copy a few Characters furtheron in this Variable, you'll mess up the result.
  69.  
  70. >      SHR CX,1
  71. >      REP MOVSW
  72. >      TEST AX,1
  73. >      JZ @end
  74. >      MOVSB
  75. > @end:POP DS
  76.  
  77. The TEST AX, 1 instruction is superfluous.  If the number of Bytes in the CX
  78. register is odd, the SHR CX, 1 instruction will set the carry bit.  It's more
  79. convenient to test this bit.  Here's how:
  80.  
  81.          SHR   CX, 1
  82.          JNC   @1
  83.          MOVSB
  84.          REP   MOVSW
  85.     @1:
  86.  
  87. > Have Fun,
  88.  
  89. No fun if source and destination overlap, as said earlier.  Here follows a
  90. memory move routine With 16-bit moves and overlap check:
  91. }
  92. Procedure MoveMem(Var source, target; size : Word); Assembler;
  93.  
  94. Asm
  95.         PUSH    DS
  96.         LDS     SI, source
  97.         LES     DI, target
  98.         MOV     CX, size
  99.         CLD
  100.  
  101.     { If an overlap of source and target could occur,
  102.       copy data backwards }
  103.  
  104.         CMP     SI, DI
  105.         JAE     @2
  106.  
  107.         ADD     SI, CX
  108.         ADD     DI, CX
  109.         DEC     SI
  110.         DEC     DI
  111.         STD
  112.  
  113.         SHR     CX, 1
  114.         JAE     @1
  115.         MOVSB
  116. @1:     DEC     SI
  117.         DEC     DI
  118.         JMP     @3
  119.  
  120. @2:     SHR     CX, 1
  121.         JNC     @3
  122.         MOVSB
  123.  
  124. @3:     REP     MOVSW
  125.         POP     DS
  126. end;  { MoveMem }
  127.  
  128.  
  129. {
  130. > For I := 0 to 200 do
  131. >  Move(Buffer,Mem[$A000:0000],320);
  132.  
  133. Looks weird to me. Why moving all that stuff 200 times to the first line
  134. of the screen ?
  135.  
  136. > For I := 100 to 200 do
  137. >  Move(Buffer[320*I],Mem[$A000:(I*320)],320);
  138.  
  139. This could be done via
  140.  
  141. Move(Buffer[320*StartLine], Mem[$a000:320*StartLine], 320*NumberOfLines) ;
  142.  
  143. which should somehow be faster.
  144.  
  145. Also note that TP's Move Procedure Uses a LODSB instruction, which is
  146. twice as slow as a LODSW instruction on 286+ computers, With big buffers.
  147. So here is a replacement Move proc, which works fine EXCEPT if the two
  148. buffers overlap and destination is at a greater address than source, which
  149. anyway is not the Case here.
  150. }
  151. Procedure FastMove(Var Src, Dst ; Cnt : Word) ;
  152. Assembler ;
  153. Asm
  154.      Mov       DX, DS         { Sauvegarde DS }
  155.      Mov       CX, Cnt
  156.      LDS       SI, Src
  157.      LES       DI, Dst
  158.      ClD                      { A priori, on va du dbut vers la fin }
  159.      ShR       CX, 1          { On va travailler sur des mots }
  160.      Rep       MovSW          { Copie des mots }
  161.      JNC       @Done          { Pas d'octet restant (Cnt pair) ? }
  162.      MovSB                    { Copie dernier octet }
  163. @Done:
  164.      Mov       DS, DX         { Restauration DS }
  165. end ;
  166. {
  167. Well, just a note : this proc works twice faster than TP's Move _only_ if
  168. Src and Dst are Word aligned, which is the Case if :
  169. - they are Variables allocated on the heap,
  170. - they are declared in the stack,
  171. - $a+ is specified,
  172. - you use it as described in your examples of code :-)
  173. }